Университет Города Переславля
Программирование для Internet
 
"Мы, может быть, найдем то, чего мы как будто не ищем, а оно-то есть, что мы на самом деле ищем."
(А.А. Милн)

Лекция 3. JavaScript. Основные понятия

Речь здесь пойдет об основных конструкциях языка JavaScript, вернее о том, что в литературе называется Core Language. Вопросы связанные с более развитыми возможностями языка, а также со связью JavaScript и web-броузеров будут рассмотрены позднее.

В принципе, знаний других языков от читателя не требуется, но те, кто знает C/C++ найдут для себя очень много знакомого.

В нашем распоряжении имеется электронная версия перевода замечательной книги Стефана Коха. Поэтому, я не буду повторять здесь все, что там написано. Пожалуйста, прежде чем читать дальше, внимательно ознакомьтесь с первой главой этой книги. Рассматривайте ее как часть излагаемого здесь материала. Я не буду его повторять.

Переменные, операции и выражения

Теперь, когда Вы просмоотрели простые примеры, пора начать готовиться к написанию более сложных, а для этого стоит вспомнить, что JavaScript все-таки язык программирования, а не набор приспособлений для начинающего фокусника.

Знакомство с любым языком программирования, обычно, начинают с тех данных, с которыми могут работать программы на этом языке. Программы на JavaScript могут работать с различными типами данных, но, в отличие от языков C, Pascal и многих других этот язык не типизирован. Это означает, что программисту не нужно описывать типы переменных. Более того, одна и та же переменная может быть в какой-то момент числом, в какой-то строкой, а потом и еще чем-нибудь.

Таким образом, наш первый вывод - JavaScript не типизированный язык и типы данных хранящиеся в переменных могут изменяться во время работы программы.

Переменные можно объявлять с помощью ключевого слова var, а можно и не объявлять. В последнем случае, переменная автоматически "объявлятся" в момент присваивания ей значения (не стоит использовать переменные, которым не были присвоены значения). Следует, однако, помнить, что переменная явно объявленная с помощью var является локальной внутри того блока, где она объявлена, а необъявленная переменная - всегда глобальна. Это очень серьезный момент и общее правило здесь таково:

в целях упрощения программ и избежания серьезных ошибок программирования, настоятельно рекомендую считать возможность вводить переменные без явного объявления несуществующей и всегда обявлять их.

Примеры объявлений переменных:

var a;                    // Объявляется переменная а
var b = 10;               // Переменная b получает начальное значение
var с = "Hello, world.";  // Переменная с получает начальное значение

Возможно, Вы заметили, что строку мы записали в двойных кавычках. Можно и в одинарных разницы нет. Более того, если строка записана в двойных кавычках, то внутри нее можно смело использовать одинарные, никакого особого смысла они там не имеют и наоборот.

Например:

document.write("Can't open document");
   // будет напечатано: Can't open document

document.write('Речь имеющую мерность я называю "поэзией"');
   // будет напечатано: Речь имеющую мерность я называю "поэзией"
	
document.write('Can't open document');
   // ОШИБКА! строка закончилась после слова Can, т.к. кавычка закрылась
	
document.write("Речь имеющую мерность я называю "поэзией"");
   // ОШИБКА! угадайте, почему

Основное действие, которое мы можем выполнить над перемнной, это присвоить ей значение.

В отличие от языка Pascal, в JavaScript нет оператора присвания, зато есть операция присваивания. Разница в том, что операция всегда имеет значение и, стало-быть им можно пользоваться в выражениях. Значением операции присваивания является то, что было присвоено. Обозначается операция присваивания символом =.

Например:

a = 10;              // a получило значение 10
b = a + 5;           // b получило значение 15
c = a + (b = a + b); // сначала b стало равно 25, а потом с - 35
                     // т.к. значением выражения (b = a + b) является
                     // то, что было присвоено, в данном случае 25 

В правой части оператора присваивания стоят выражения. Операции над числами традиционны. Это сложение (+), вычитание (-), умножение (*), деление (/) и взятие остатка от деления (%).

Все перечисленные операции можно объединять со знаком =. Это приводит к бюолее коротко записи программ и более эффективному коду.

a += 10; // эквивалентно a = a + 10;
a -= 10; // эквивалентно a = a - 10;
a *= 10; // эквивалентно a = a * 10;
a /= 10; // эквивалентно a = a / 10;
a %= 10; // эквивалентно a = a % 10;

Операция сложения (+) применима также и для строк и означает конкатенацию. Если только один из операндов - строка, а второй число, то второй преобразуется в строку.

Например:

a = 2+5;     // a получило значение 7 (число)
b = "2"+"5"; // b получило значение "25" (строка)
c = ""+2+5+6;// b получило значение "256" (строка), т.к. одним из
             // первым аргументом была строка
c = 2+5+""+6;// b получило значение "76" (строка), т.к. сначала
             // сложились числа 2+5, потом система "заметила", что
             // дальше идет строка и преобразовала первое слагаемое
             // в строку же. Т.е. получили тоже, как если бы записать
             // c = (2+5)+""+6;

Как Вы уже заметили, в выражениях могут использоваться и операции присваивания. В отличие от арифметических операций, присвания выполняются справа налево.

a = b = c = d = 5;  // сначала d получит значение 5, затем
                    // результат этой операции (5) будет присвоен c,
                    // затем - b, и, наконец, - a. Т.е. все переменные
                    // получат значение 5

Кроме арифметических, существуют логические выражения. Это такие выражения, которые могут принимать значения истина и ложь.

Подобно языку C, здесь нет специальных слов для обозначения этих понятий. Вместо них используется следующее правило: число 0 или пустая строка обозначают ложь. Все, остальное - обозначает истину. Таким образом, если Вам потребуется логическое выражение, которое всегда истинно - не мудрствуйте лукаво, а пишите просто любое отличное от нуля число или любую непустую строку, например 1 или "true".

Логические выражения образутся, также, при операциях сравнения. В языке представлены традиционные операции: "больше" (>), "меньше" (<), "равно" (==) (ДВА знака равенства подряд, без пробела!), "больше или равно" (>=), "меньше или равно" (<=) и не равно (!=).

Сравнение чисел работает как обычно. Сравнение строк - по алфавиту. Если один операнд число, а другой строка - то число предбразуется в строку и они сравниваются как строки.

И, наконец, между двумя логическими выражениями можно ставить логические операции: "И" (&&), "ИЛИ" (||), а перед логическим выражением может стоять отрицание (!).

Кажется, настала пора добраться до примеров:

0 ложь - число 0
"" ложь - пустая строка
"0" истина - непустая строка
"1 > 100" истина - непустая строка
1 > 100 ложь - ну, с чего бы единице быть больше 100?
23 > 3 истина - ну, еще бы!
"23" > "3" ложь - строка "23" по алфавиту идет раньше, чем строка "3"
(1 > 100) || "Обманули" истина - первое выражение ложно, но, через ИЛИ, с ним стоит непустая строка, т.е. истинное выражение
(a != 5) || (a != 10) истина независимо от значения a! Там ведь стоит ИЛИ, а уж хотябы одному из чисел 5 или 10 переменная a точно не равна!
(a < 5) && (a > 10) ложь независимо от значения a! Не может ведь бедная переменная быть одновременно И меньше пяти И больше десяти!

Операции увеличения и уменьшения на 1. Записываются как ++ и --. Применяются только к числам. Если записаны ДО переменной, то изменяют значение переменной ДО ее использования. Если ПОСЛЕ, то после использования.

Например:

var b=2;
a = b++; // a получит значение 2, после этого b увеличится 1
a = ++b; // сначала b увеличится 1 (станет 4), а затем
         // это значение (4) будет присвоено a
a = a+b--; // сначала а получит значение 8,
           // а затем b уменьшится на 1			

Существует еще одна операция, позаимствованная из языка C. Но, она может показаться несколько необычной для начинающих, поэтому, сначала, я хочу напомнить, что: операция, это нечто, имеющее значение, которое, затем, можно использовать (присвоить чему нибудь или еще как). Например, сложение, это операция. Можно, например записать a=b+c. Переменная a получит значение равное значению операции сложения над операндами b и c.

Вооружившись таким определением операции, рассмотри условную операцию. Выглядит она так:

   (<логическое выражение>) ? выражение1 : выражение2

Значением этой операции будет значение выражения1, если условие истинно и значение выражения2, если условие ложно.

Например:

a = (b>c) ? b : c;     // a получит значение большего из b и c
a = ((b>c) ? b : c)+1; // a получит значение большего из b и c
                       // увеличенное на 1
a = (b % 2) ? "нечетное" : "четное";

Операторы

Оператор if

Условный оператор точно такой же как в языке C.

if (<логическое выражение>) оператор1;
[else оператор2;]

Выполняется он так: сначала вычисляется логическое выражение. Если оно истинно, то выполняется оператор1. Если же оно ложно, то вычисляется оператор2 (если таковой имеется). В качестве операторов могут использоваться любые операторы языка, в том числе и еще один if.

Здесь и далее, везде, где мы имеем право поставить один оператор, мы имеем право поставить и несколько операторов, заключенных в фигурные скобки. Такой "составной" оператор называется блоком.

Например:

if (a>b) document.write("А больше B");
else document.write("А НЕ больше B");

if (day==1) document.write("понедельник");
else if (day==2) document.write("вторник");
else if (day==3) document.write("среда");
else if (day==4) document.write("четверг");
else if (day==5) document.write("пятница");
else if (day==6) document.write("суббота");
else if (day==7) document.write("воскресенье");
else document.write("Ошибка: day="+day);

Цикл while

И этот такой же как в языке C.

while (<логическое выражение>) оператор;

Сначала вычисляется логическое выражение. Если оно истинно, то выполняется оператор. Затем снова вычисляется логическое выражение. Если оно и на этот раз истинно - снова выполняется оператор и снова вычисляется логическое выражение.

Так продолжается до тех пор, пока логическое выражение не станет ложным. Как только, при очередном вычислении, логическое выражение оказалось ложным, оператор не выполняется, а выполнение программы продолжается с точки следующей сразу за оператором.

Например:

var i = 0;
while (i<10) {
   document.write("*");
   i = i+1;
}
document.write(i);
В этом примере будет напечатано 10 звездочек, а, затем, число 10.

Еще пример:

var i = 0;
while (i>10) {
   document.write("*");
   i = i+1;
}
document.write(i);

Ни одной звездочки напечатано не будет, т.к. логическое выражение (i>10) ложно с самого начала. Просто будет напечатано число 0.

Последний пример:

var i = 0;
while (i<10) {
   document.write("*");
}
document.write(i);

Звездочки будут печататься бесконечно, т.к. логическое выражение никогда не станет ложным. Действительно, i вседа будет оставаться нулем и будет меньше 10.

Цикл for

Этот, довольно сложный цикл, также имеет двойника в языке C.

В принципе, без него можно и обойтись, потому, что все, что он делает, можно записать и с помощью простого цикла while, однако иногда цикл for приводит к более простым и изящным программам.

for (выражение1;выражение2;выражение3) оператор;

Выполняется он таким образом:

  1. Вычисляется выражение1
  2. Вычисляется выражение2
  3. Если выражение2 можно рассматривать как истину (либо оно было логическим, либо оно не равно ни нулю, ни пустой строке) то выполняется оператор, иначе цикл заверщается и программа продолжает выполнение с точки следующей за оператором.
  4. Вычисляется выражение3
  5. Переход к шагу 2

Таким образом, мы можем записать полный эквивалент цикла for при помощи простого while.

выражение1;
while (выражение2) {
   оператор;
   выражение3	
}

Заметьте, что выражение1 вычисляется всегда и только один раз, в самом начале. Выражение2 всегда вычисляется хотябы один раз. И, наконец, выражение3 и оператор могут не вычисляться и ни разу в том случае, когда выражение2 изначально ложно.

Любое (хоть все сразу) из выражений в цикле for можно опускать. Но, при этом нельзя выбрасывать точки с запятыми. Их всегда должно быть две. Опущенное выражение считается истинным.

Примеры:

// Печатаем 10 звездочек
for (var i=0; i<10; i++) document.write('*');

// Печатаем нечетные числа меньшие 100
for (var i=1; i<100; i+=2) document.write(i);

// Печатаем четные числа от 100 до 200
for (var i=100; i<=200; i+=2) document.write(i);

// Печатаем все степени числа 2 до 4096
for (var i=2; i<=4096; i*=2) document.write(i);

Date и Math

Очень многое в языке JavaScript строится на понятии объекта. Мы рассмотрим что это такое, на последующих лекциях. Сейчас же мы воспользуемся (пока вслепую) двумя встроенными объектами языка - Math и Date. (По правде говоря, мы, втихаря, уже пользовались объектами. Когда мы писали document.write, мы пользовались объектом document.)

Мы бы не стали рассматривать эти объекты сейчас, но надо же нам иметь хоть что-то кроме чисел и строк для того, чтобы попробовать попрограммировать!

Все, что нам сегодня потребуется от объекта Math, это получать последовательности псевдослучайных чисел и вычислять тригонометрические функции. Позднее, мы вернемся к нему и рассмотрим его подробнее.

Чтобы получить последовательность пседо-случайных чисел равномерно распределенных на интервале 0-1, достаточно обратиться к функции random объекта Math. Для этого нужно записать имя обекта и через точку от него имя функции:

var a = Math.random(); // a получило случайное значение от 0 до 1 

Обратите внимание, что после имени функции обязательно пишется список аргументов, даже если он и пустой.

Следующий фрагмент программы, с вероятность 0.4 печатает слово ДА или НЕТ, а с вероятностью 0.2 печатает НЕ ЗНАЮ.

var a = Math.random(); // a получило случайное значение от 0 до 1 
if (a < 0.4) document.write("ДА");
else if (a < 0.8) document.write("НЕТ");
else document.write("НЕ ЗНАЮ");

Тригонометрические функции вычисляются аналогично:

document.write("sin(0.5)="+Math.sin(0.5));
document.write("cos(4)="+Math.cos(4));
document.write("tg(0.1)="+Math.tan(0.1));

С объектом Date несколько сложнее. Для начала, переменную типа Date нужно создать. Создать ее можно разными способами. Мы рассмотрим четыре.

  1. Для того чтобы присвоить переменной значение текущей даты и текущего времени (на момент загрузки Вашей страницы пользователем), достаточно написать: var a = new Date();
  2. Чтобы присвоить переменной занчение некоторой конкретной даты, пишем: var a = new Date(yyyy,mm,dd);
  3. Чтобы присвоить переменной занчение некоторой конкретной даты и времени суток, пишем: var a = new Date(yyyy,mm,dd,hh,mm,ss);
  4. Чтобы создать новую переменную типа Date и присвоить ей значение уже существующей, пишем: var a = new Date(otherDate.getTime());

Месяцы нумеруются с нуля. 0 - январь, 1 - февраль и т.д.

Примеры:

// переменная now получает значение текущей даты и времени
var now = new Date(); 

// переменная birthday получает значение 20 июня 1981 г.
var birthday = new Date(1981,5,20); 

// переменная exam получает значение 5 января 1999 г. 10 часов 30 минут
var exam = new Date(1981,5,20,10,30,0); 

После того как переменная создана, "у нее можно узнать", дату и время записанную в ней. Можно также и переустановить дату и время. Для этого существует целый ряд функций. Мы рассмотрим лишь несколько.

Функция Описание
getYear() Возвращает год
setYear() Устанавливает год
getMonth() Возвращает месяц. 0-январь, 1-февраль и т.д.
setMonth() Устанавливает месяц
getDate() Возвращает день месяца. Число от 1 до 31.
setDate() Устанавливает день месяца
getDay() Возвращает день недели. 0-воскресенье, 1-понедельник, и т.д.
getHours() Возвращает час. Число от 0 до 23
setHours() Устанавливает час. Число от 0 до 23
getMinutes() Возвращает минуту. Число от 0 до 59
setMinutes() Устанавливает минуту. Число от 0 до 59
getTime() Возвращает количество миллискунд прошедших с 0 часов 1 января 1970
setTime() Устанавливает дату и время. Обратная getTime()

Пример. Попробуем напечатать номер текущего дня в году.

// Текущее время и дата
var today = new Date();

// начало текущего года
var yearBegin = new Date(today.getYear(),0,1);

// переменна d - количество миллисекунд от начала года.
var d = today.getTime() - yearBegin.getTime();

// поделим d на количество миллисекунд в сутках
d /= (1000*60*60*24);

// прибавим 1, иначе 1 января будет нулевым днем
d++;

// печать результата
document.write("Сегодня "+d+" день с начала года");

Внимание При исользовании Netscape Navigator, возникают проблемы с русскими буквами 'я' и 'C' в программах на JavaScript. Их можно использовать только внутри строк (внутри кавычек) и обязательно ставить перед ними символ '\'. Например, строка "Свинья" вызовет сбой в работе Netscape. Следует писать "\Свинь\я".



До сессии всего 35 дней!!!

Главная страница Замечания? Комментарии? Идеи?